package com.my.chapter17;

public class practice28 {
    public static void main(String[] args) {
        Tuple.T3<String,Integer,Boolean>
                t1 = Tuple.tuple("he",6,true),
                t2 = Tuple.tuple("he",3,false);
        System.out.println("t1 = " + t1);
        System.out.println("t2 = " + t2);
        System.out.println("t1.equals(t1) = " + t1.equals(t1));
        System.out.println("t1.equals(t2) = " + t1.equals(t2));
        System.out.println("t1.compareTo(t1) = " + t1.compareTo(t1));
        System.out.println("t1.compareTo(t2) = " + t1.compareTo(t2));
    }
}


class Tuple {
    public static class T2<A,B>
            implements Comparable<T2<A,B>> {
        private final A first;
        private final B second;
        public T2(A a, B b) {
            first = a;
            second = b;
        }
        public String toString() {
            return "(" + first + ", " + second + ")";
        }
        public int hashCode() {
            int result = 17;
            if(first != null)
                result = result * 37 + first.hashCode();
            if(second != null)
                result = result * 37 + second.hashCode();
            return result;
        }
        public boolean equals(Object obj) {
            if(obj instanceof T2) {
                @SuppressWarnings("unchecked")
                T2<A,B> o = (T2<A,B>)obj;
                return (first == null ?
                        o.first == null : first.equals(o.first)) &&
                        (second == null ?
                                o.second == null : second.equals(o.second));
            }
            return false;
        }
        @SuppressWarnings("unchecked")
        public int compareTo(T2<A,B> o) {
            int res = ((Comparable<A>)first).compareTo(o.first);
            if(res != 0) return res;
            return ((Comparable<B>)second).compareTo(o.second);
        }
        public A getFirst() { return first; }
        public B getSecond() { return second; }
    }
    public static class T3<A,B,C>
            implements Comparable<T3<A,B,C>> {
        private final T2<A,B> tuple;
        private final C third;
        public T3(A a, B b, C c) {
            tuple = new T2<A,B>(a, b);
            third = c;
        }
        public String toString() {
            return "(" + tuple.getFirst() + ", " +
                    tuple.getSecond() + ", " + third +")";
        }
        public int hashCode() {
            int result = tuple.hashCode();
            if(third != null)
                result = result * 37 + third.hashCode();
            return result;
        }
        public boolean equals(Object obj) {
            if(obj instanceof T3) {
                @SuppressWarnings("unchecked")
                T3<A,B,C> o = (T3<A,B,C>)obj;
                return (third == null ?
                        o.third == null : third.equals(o.third)) &&
                        tuple.equals(o.tuple);
            }
            return false;
        }
        @SuppressWarnings("unchecked")
        public int compareTo(T3<A,B,C> o) {
            int res = tuple.compareTo(o.tuple);
            if(res != 0) return res;
            return ((Comparable<C>)third).compareTo(o.third);
        }
        public A getFirst() { return tuple.getFirst(); }
        public B getSecond() { return tuple.getSecond(); }
        public C getThird() { return third; }
    }

    public static <A,B> T2<A,B> tuple(A a, B b) {
        return new T2<A,B>(a, b);
    }
    public static <A,B,C> T3<A,B,C> tuple(A a, B b, C c) {
        return new T3<A,B,C>(a, b, c);
    }
}
